<html>
	<head>
		<title>JSEV additionalProperties Test</title>
		<script type="application/javascript" src="../methods.Object.js"></script>
		<script type="application/javascript" src="../methods.Array.js"></script>
		<script type="application/javascript" src="../JSON.schema.reg.js"></script>
		<script type="application/javascript" src="../JSON.path.js"></script>
		<script type="application/javascript" src="../JSON.schema.err.js"></script>
		<script type="application/javascript" src="../JSON.schema.err.messages.en.js"></script>
		<script type="application/javascript" src="../JSON.schema.ext.walker.js"></script>
		<script type="application/javascript" src="../JSON.schema.ext.js"></script>
		<script type="application/javascript">
			function validTest() {
				var schemaA = {"id": "schemaA", "type": "object"},
					schemaB = {"id": "schemaB"},
					schemaC = {"id": "schemaC"},
					schemaD = {"id": "schemaD", "extends": "schemaC"},
					schemaE = {"id": "schemaE", "additionalProperties": {"type": "number"}},
					schemaF = {"id": "schemaF", "properties": {"prop1": {"type": "integer"}, "prop2": {"type": "number"}}},
					schemaG = {"id": "schemaG", "properties": {"prop1": {"type": "integer", "optional": true}, "prop2": {"type": "number"}}},
					/** Shouldn't produce RequiredTypeError RTE000 */
					schema0 = {"type": "object", "additionalProperties": {}},
					schema1 = {"additionalProperties": {}},
					schema2 = {"type": "schemaA", "additionalProperties": {}},
					schema3 = {"extends": "schemaA", "additionalProperties": {}},
					schema4 = {"type": "schemaB", "additionalProperties": {}},
					schema5 = {"extends": "schemaB", "additionalProperties": {}},
					schema6 = {"type": "schemaD", "additionalProperties": {}},
					schema7 = {"extends": "schemaD", "additionalProperties": {}},
					/** Shouldn't produce SubTypeError STE004 */
					schema8 = {"type": "schemaE", "additionalProperties": {"type": "integer"}},
					schema9 = {"extends": "schemaE", "additionalProperties": {"type": "integer"}},
					/** Shouldn't produce SubTypeError STE008 */
					schema10 = {"type": "schemaF", "properties": {"prop2": {"type": "integer"}}, "additionalProperties": {"type": "integer"}},
					schema11 = {"extends": "schemaF", "properties": {"prop2": {"type": "integer"}}, "additionalProperties": {"type": "integer"}},
					/** Shouldn't produce InvalidValueError IVE006 */
					schema12 = {"type": "schemaG", "properties": {"prop2": {"type": "integer"}}, "additionalProperties": false},
					schema13 = {"extends": "schemaG", "properties": {"prop2": {"type": "integer"}}, "additionalProperties": false},
					schemasToValidate = [
						schema0, schema1, schema2, schema3, schema4, schema5, schema6, schema7,
						schema8, schema9,
						schema10, schema11,
						schema12, schema13
					],
					retVal = undefined;

				try {
					JSON.schema.registry.unregister("*");
					JSON.schema.registry.register([schemaA, schemaB, schemaC, schemaD, schemaE, schemaF, schemaG]);
				} catch (e) {
					console.error("Type registration failed: ", e);
				}

				for (var i in schemasToValidate) {
					retVal = JSON.schema.ext.validate(schemasToValidate[i]);
					if (retVal.valid) {
						console.info("Test " + i + " passed!", retVal);
					} else {
						console.warn("Test " + i + " failed.", retVal);
						if (retVal.errors.length > 0) {
							console.group("Error messages:");
							for (var i in retVal.errors) {
								console.info(JSON.schema.err.localize("en", retVal.errors[i]));
							}
							console.groupEnd();
						} else {
							console.info("No errors reported.");
						}
					}
				}
			}

			function invalidTest() {
				var schemaA = {"id": "schemaA", "type": "integer"},
					schemaB = {"id": "schemaB", "type": ["object", "array"], "disallow": "object"},
					schemaC = {"id": "schemaC", "disallow": "object"},
					schemaD = {"id": "schemaD", "type": ["object", "array"], "extends": "schemaC"},
					schemaE = {"id": "schemaE", "additionalProperties": {"type": "number"}},
					schemaF = {"id": "schemaF", "properties": {"prop1": {"type": "integer"}, "prop2": {"type": "number"}}},
					schemaG = {"id": "schemaG", "properties": {"prop1": {"type": "integer", "optional": true}, "prop2": {"type": "number"}}},
					/** RequiredTypeError RTE000 */
					schema0 = {"type": "integer", "additionalProperties": {}},
					schema1 = {"type": ["object", "array"], "disallow": "object", "additionalProperties": {}},
					schema2 = {"type": "schemaA", "additionalProperties": {}},
					schema3 = {"extends": "schemaA", "additionalProperties": {}},
					schema4 = {"type": "schemaB", "additionalProperties": {}},
					schema5 = {"extends": "schemaB", "additionalProperties": {}},
					schema6 = {"type": "schemaD", "additionalProperties": {}},
					schema7 = {"extends": "schemaD", "additionalProperties": {}},
					/** SubTypeError STE004 */
					schema8 = {"type": "schemaE", "additionalProperties": {"type": "string"}},
					schema9 = {"extends": "schemaE", "additionalProperties": {"type": "string"}},
					/** SubTypeError STE008 */
					schema10 = {"type": "schemaF", "properties": {"prop2": {"type": "integer"}}, "additionalProperties": {"type": "string"}},
					schema11 = {"extends": "schemaF", "properties": {"prop2": {"type": "integer"}}, "additionalProperties": {"type": "string"}},
					/** InvalidValueError IVE006 */
					schema12 = {"type": "schemaG", "properties": {"prop2": {"type": "integer", "optional": true}}, "additionalProperties": false},
					schema13 = {"extends": "schemaG", "properties": {"prop2": {"type": "integer", "optional": true}}, "additionalProperties": false},
					/** InvalidValueError IVE007 */
					schema14 = {"type": "schemaG", "properties": {"prop1": {"type": "integer"}}, "additionalProperties": false},
					schema15 = {"extends": "schemaG", "properties": {"prop1": {"type": "integer"}}, "additionalProperties": false},
					errorsExpected = [
						["RTE000"], ["RTE000"], ["RTE000"], ["RTE000"], ["RTE000"], ["RTE000"], ["RTE000"], ["RTE000"],
						["STE004"], ["STE004"],
						["STE008"], ["STE008"],
						["IVE006"], ["IVE006"],
						["IVE007"], ["IVE007"]
					],
					schemasToValidate = [
						schema0, schema1, schema2, schema3, schema4, schema5, schema6, schema7,
						schema8, schema9,
						schema10, schema11,
						schema12, schema13,
						schema14, schema15
					],
					retVal = undefined;

				try {
					JSON.schema.registry.unregister("*");
					JSON.schema.registry.register([schemaA, schemaB, schemaC, schemaD, schemaE, schemaF, schemaG]);
				} catch (e) {
					console.error("Type registration failed: ", e);
				}

				function correctErrors(vRetVal, errorsExpected) {
					if (vRetVal.errors.length != errorsExpected.length)
						return false;

					var i = 0;
					for (; i < errorsExpected.length; i++) {
						if (errorsExpected[i] != vRetVal.errors[i].code) {
							return false;
						}
					}
					return true;
				}

				for (var i in schemasToValidate) {
					retVal = JSON.schema.ext.validate(schemasToValidate[i]);
					if (!retVal.valid && correctErrors(retVal, errorsExpected[i])) {
						console.info("Test " + i + " passed!", retVal);
						if (document.getElementById("showInvMsg").checked) {
							console.group("Error Messages for expected errors:");
							for (var j in retVal.errors)
								console.info(JSON.schema.err.localize("en", retVal.errors[j]));
							console.groupEnd();
						}
					} else {
						console.warn("Test " + i + " failed.", retVal);
						console.group("Reason: ");
						var loops = errorsExpected[i].length > retVal.errors.length ?
							errorsExpected[i].length : retVal.errors.length;
						var msg = "";

						if (loops == 0) {
							console.info("The schema was marked as valid yet it should have been invalid.");
						} else {
							for (var j = 0; j < loops; j++) {
								if (
									j in errorsExpected[i] && j in retVal.errors &&
									errorsExpected[i][j] == retVal.errors[j].code
								) continue;

								if (j in errorsExpected[i])
									msg += "Error Expected: " + errorsExpected[i][j];
								else
									msg += "No error expected";

								if (j in retVal.errors)
									msg += ", found: " + retVal.errors[j].code + ".";
								else
									msg += ", no error found."

								console.info(msg);
								msg = "";
							}
						}
						console.groupEnd();
					}
				}
			}
		</script>
	</head>
	<body>
		<div> Tests the `additionalProperties' restriction check of JSON.schema.ext.validate </div>
		<div><button onclick="validTest();">Valid Schema Test</button></div>
		<div><button onclick="invalidTest();">Invalid Schema Test</button><input type="checkbox" id="showInvMsg"></input><label for="showInvMsg">Show Messages</label></div>
	</body>
</html>